#include "ahxgwnet.h"

namespace ahxgwnet {

/**
 * 构造函数
 */
IOWrapper::IOWrapper(int fd)
{
    m_fd = fd;
}

void IOWrapper::setFd(int fd)
{
    m_fd = fd;
}


/**
 * 读取N个字节数据
 *
 * @param *vptr 读到数据存放的位置指针
 * @param n 读的字节数
 * @return 实际读到的字节数 -1出错 0对方中止
 */
ssize_t IOWrapper::readN(void *vptr, size_t n)
{
    size_t  nLeft   = n;
    ssize_t nRead   = 0;
    char    *ptr    = (char *)vptr;

    while (nLeft > 0)
    {
        nRead = read(m_fd, vptr, nLeft);
        if (nRead == 0)
            break;
        if (nRead < 0)
        {
            if (errno == EINTR)
                nRead = 0;
            else
                return -1;
        }
        
        nLeft -= nRead;
        ptr += nRead;
    }
    return n - nLeft;
}

/**
 * 写N个字节数据
 *
 * @param *vptr 待写数据的首地址
 * @param n 写的字节数
 * @return 实际写的字节数 -1出错
 */
ssize_t IOWrapper::writeN(const void *vptr, size_t n)
{
    size_t  nLeft   = n;
    ssize_t nWrite  = 0;
    char    *ptr    = (char *)vptr;

    while (nLeft > 0)
    {
        nWrite = write(m_fd, ptr, nLeft);
        if (nWrite < 0 && errno == EINTR)
            nWrite = 0;
        else if (nWrite <= 0)
        {
            perror("write error");
            return -1;
        }

        //fprintf(stderr, "writeN: write %d bytes\n", nWrite);
        nLeft -= nWrite;
        ptr += nWrite;
    }
    return n;
}

/**
 * readLine使用的read函数，先读到m_readBuf中，再一个个返回给readLine
 *
 * @param *ptr 存读到数据的地址
 * @return 读到的字节数，-1出错，0对方中止，1正常
 */
ssize_t IOWrapper::myRead(char *ptr)
{
    while (m_readCnt <= 0)
    {
        m_readCnt = read(m_fd, m_readBuf, MAXLINE);
        if (m_readCnt == 0)
            return 0;
        if (m_readCnt < 0)
        {
            if (errno == EINTR)
                continue;
            return -1;
        }
        m_readPtr = m_readBuf;
    }

    m_readCnt--;
    *ptr = *m_readPtr++;
    return 1;
}

/**
 * 读取一行数据
 *
 * @param *vptr 读到数据存放的位置指针 
 * @param maxLen 最大字节数
 * @return 实际读的字节数 -1出错
 */
ssize_t IOWrapper::readLine(void *vptr, size_t maxLen)
{
    int n, rc;
    char c, *ptr = (char *)vptr;    

    for (n = 1; n < maxLen; n++)
    {
        rc = myRead(&c);
        if (rc == -1)
            return -1;
        if (rc == 0)
        {
            *ptr = 0;
            return n - 1;
        }
        *ptr++ = c;
        if (c == '\n')
            break;
    }

    *ptr = 0;
    return n;
}

/**
 * 检查myRead中缓存剩余的数据
 *
 * @param **vptrPtr 保存剩余数据的首地址
 * @return 剩余的字节数
 */
ssize_t IOWrapper::readLineBuf(void **vptrPtr)
{
    if (m_readCnt)
        *vptrPtr = m_readPtr;
    return m_readCnt;
}

}
